package com.cloud.punish.tasklist.service.impl;

import java.sql.PreparedStatement;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;

import com.cloud.punish.tasklist.service.TaskListMenuCalculateService;
import org.apache.commons.lang.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.jdbc.core.BatchPreparedStatementSetter;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import com.cloud.punish.common.result.QkIcon;
import com.cloud.punish.common.result.QkTreeNode;
import com.cloud.punish.common.utils.SessionHelper;
import com.cloud.punish.tasklist.bean.MenuTabAuthority;
import com.cloud.punish.tasklist.bean.Part;
import com.cloud.punish.tasklist.bean.TabMenuHeader;
import com.cloud.punish.tasklist.entity.TaskListMenuPart;
import com.cloud.punish.tasklist.entity.TaskListMenu;
import com.cloud.punish.tasklist.entity.TaskListMenuGroup;
import com.cloud.punish.tasklist.mapper.TaskListMenuPartMapper;
import com.cloud.punish.tasklist.mapper.TaskListMenuGroupMapper;
import com.cloud.punish.tasklist.mapper.TaskListMenuMapper;
import com.cloud.punish.tasklist.service.TaskListMenuService;

import tk.mybatis.mapper.entity.Example;

@Service
@Transactional
public class TaskListMenuServiceImpl implements TaskListMenuService {

    @Autowired
    private TaskListMenuGroupMapper taskListMenuGroupMapper;
    @Autowired
    private TaskListMenuMapper taskListMenuMappler;
    @Autowired
    private TaskListMenuPartMapper menuPartMapper;
    @Autowired
    private TaskListMenuCalculateService taskListMenuCalculateService;
    @Autowired
    private JdbcTemplate jdbcTemplate;


    @Override
    public List<QkTreeNode> listTree() {
        Example grpExample = new Example(TaskListMenuGroup.class);
        Example.Criteria grpCriteria = grpExample.createCriteria();
        grpCriteria.andEqualTo("deleteFlag", 0);
        grpExample.orderBy("displayOrder").asc();
        List<TaskListMenuGroup> groups = taskListMenuGroupMapper.selectByExample(grpExample);
        Example menuExample = new Example(TaskListMenu.class);
        Example.Criteria menuCriteria = menuExample.createCriteria();
        menuCriteria.andEqualTo("deleteFlag", 0);
        menuExample.orderBy("displayOrder").asc();
        List<TaskListMenu> menus = taskListMenuMappler.selectByExample(menuExample);
        List<QkTreeNode> nodes = new ArrayList<QkTreeNode>();
        for (TaskListMenuGroup group : groups) {
            QkTreeNode grpNode = new QkTreeNode("grp_" + group.getGroupId(), group.getGroupName());
            grpNode.setCollapsedIcon(QkIcon.FA_FOLDER);
            grpNode.setExpandedIcon(QkIcon.FA_FOLDER_OPEN);
            grpNode.setRootFlag(true);
            grpNode.setSelectable(true);
            grpNode.setExpanded(true);
            for (TaskListMenu menu : menus) {
                if (menu.getGroupId().equals(group.getGroupId())) {
                    QkTreeNode menuNode = new QkTreeNode(menu.getMenuId(), menu.getMenuName());
                    menuNode.setSeniorId("grp_" + group.getGroupId());
                    menuNode.setSelectable(true);
                    menuNode.setLeaf(true);
                    menuNode.setIcon(QkIcon.FA_LAPTOP);
                    grpNode.getChildren().add(menuNode);
                }
            }
            nodes.add(grpNode);
        }
        return nodes;
    }

    @Override
    public List<TabMenuHeader> listTaskListMenuHeader() {
        Example grpExample = new Example(TaskListMenuGroup.class);
        grpExample.orderBy("displayOrder").asc();
        List<TaskListMenuGroup> groups = taskListMenuGroupMapper.selectByExample(grpExample);
        Example menuExample = new Example(TaskListMenu.class);
        menuExample.orderBy("displayOrder").asc();
        List<TaskListMenu> menus = taskListMenuMappler.selectByExample(menuExample);

        List<TabMenuHeader> results = new ArrayList<TabMenuHeader>();
        for (TaskListMenuGroup grp : groups) {
            TabMenuHeader father = new TabMenuHeader();
            father.setId(grp.getGroupId());
            father.setHeader(grp.getGroupName());
            father.setField(grp.getGroupName());
            for (TaskListMenu menu : menus) {
                if (menu.getGroupId().equals(grp.getGroupId())) {
                    TabMenuHeader child = new TabMenuHeader();
                    child.setId(menu.getMenuId());
                    child.setHeader(menu.getMenuName());
                    child.setField(menu.getMenuId() + "");
                    child.setWidth(100);
                    father.getChildren().add(child);
                }
            }
            if (father.getChildren().size() > 0) {
                father.setWidth(father.getChildren().size() * 100);
                results.add(father);
            }
        }
        return results;
    }

    @Override
    public void saveUpdatePartAuth(List<MenuTabAuthority> parts, long actDefId, long taskListId) {
        Example exp = new Example(TaskListMenuPart.class);
        Example.Criteria criteria = exp.createCriteria();
        criteria.andEqualTo("taskListId", taskListId);
        criteria.andEqualTo("actDefId", actDefId);
        menuPartMapper.deleteByExample(exp);
        List<TaskListMenuPart> partMenus = new ArrayList<TaskListMenuPart>();
        for (MenuTabAuthority part : parts) {
            TaskListMenuPart tPart = new TaskListMenuPart();
            tPart.setTaskListId(taskListId);
            tPart.setActDefId(actDefId);
            tPart.setPartId(part.getPartId());
            tPart.setMenuId(part.getMenuTabId());
            tPart.setAuthCode(part.getCode());
            partMenus.add(tPart);
        }
        final List<TaskListMenuPart> pts = partMenus;
        jdbcTemplate.batchUpdate(
                "insert into task_list_menu_part(task_list_id, act_def_id, part_id, menu_id, auth_code) values (?, ?, ?, ?, ?)",
                new BatchPreparedStatementSetter() {
                    @Override
                    public void setValues(PreparedStatement ps, int i) throws SQLException {
                        TaskListMenuPart p = pts.get(i);
                        ps.setLong(1, p.getTaskListId());
                        ps.setLong(2, p.getActDefId());
                        ps.setLong(3, p.getPartId());
                        ps.setLong(4, p.getMenuId());
                        ps.setInt(5, p.getAuthCode());
                    }

                    @Override
                    public int getBatchSize() {
                        return pts.size();
                    }
                });

    }

    @Override
    public List<Part> listPartAuthority(long taskListId, long actDefId, List<Part> parts) {
        Example example = new Example(TaskListMenu.class);
        example.orderBy("displayOrder").asc();
        List<TaskListMenu> menus = taskListMenuMappler.selectByExample(example);
        // 先设置所有的tab为默认权限
        for (Part p : parts) {
            for (TaskListMenu menu : menus) {
                p.getAuths().put(menu.getMenuId(), menu.getDefaultAuth());
            }
        }
        // 设置所有参与者配置的权限
        Example menuPartsExample = new Example(TaskListMenuPart.class);
        Example.Criteria tpCriteria = menuPartsExample.createCriteria();
        tpCriteria.andEqualTo("actDefId", actDefId);
        tpCriteria.andEqualTo("taskListId", taskListId);
        List<TaskListMenuPart> menuParts = menuPartMapper.selectByExample(menuPartsExample);

        // 配置权限优先于默认权限
        for (Part p : parts) {
            Map<Long, Integer> auths = p.getAuths();
            for (TaskListMenuPart tp : menuParts) {
                if (tp.getPartId().equals(p.getPartId())) {
                    auths.put(tp.getMenuId(), tp.getAuthCode());
                }
            }
        }
        return parts;
    }

    @Override
    public List<TaskListMenu> listTaskListMenuByPart(long taskListId, long actDefId, String poz, Long actId) {
        // 环节权限配置菜单
        Set<Long> menuIds = new HashSet<Long>();
        if (actDefId != 0) {
            Example example = new Example(TaskListMenuPart.class);
            Example.Criteria criteria = example.createCriteria();
            criteria.andEqualTo("taskListId", taskListId);
            criteria.andIn("actDefId", Arrays.asList(new Long[]{0L, actDefId}));
            criteria.andEqualTo("authCode", 1);
            criteria.andIn("partId", SessionHelper.get().getParts());
            List<TaskListMenuPart> menuParts = menuPartMapper.selectByExample(example);
            for (TaskListMenuPart mp : menuParts) {
                menuIds.add(mp.getMenuId());
            }
        }

        if (menuIds.size() == 0) {
            //未配置菜单权限的添加默认菜单
            List<Long> defaultMenus = loadDefaultMenu();
            menuIds.addAll(defaultMenus);
        }

        // 环节无关，人有的菜单
        List<Long> menus = menuPartMapper.loadUnActMenu(taskListId, SessionHelper.get().getParts());
        menuIds.addAll(menus);


        if (menuIds.size() > 0) {
            Example menuExample = new Example(TaskListMenu.class);
            Example.Criteria menuCriteria = menuExample.createCriteria();
            menuCriteria.andIn("menuId", menuIds);
            if (!StringUtils.isEmpty(poz)) {
                //查询在列表显示，和全部显示的按钮
                List<Integer> pozList = new ArrayList<>();
                pozList.add(1);
                pozList.add(3);
                menuCriteria.andIn("pozAttr", pozList);
            }
            menuExample.orderBy("displayOrder");
            List<TaskListMenu> taskListMenus = taskListMenuMappler.selectByExample(menuExample);


            taskListMenus = taskListMenuCalculateService.getTaskListMenus(actId, taskListMenus);

            return taskListMenus;

        }
        return null;
    }


    public List<Long> loadDefaultMenu() {
        List<Long> list = new ArrayList<>();
        Example example = new Example(TaskListMenu.class);
        Example.Criteria criteria = example.createCriteria();
        criteria.andEqualTo("defaultAuth", 1);
        List<TaskListMenu> menus = taskListMenuMappler.selectByExample(example);
        for (TaskListMenu menu : menus) {
            list.add(menu.getMenuId());
        }
        return list;
    }

    @Override
    public long saveUpdateGroup(TaskListMenuGroup group) {
        if (null == group.getGroupId() || 0 == group.getGroupId()) {
            group.setDeleteFlag(0);
            taskListMenuGroupMapper.insert(group);
        } else {
            group.setDeleteFlag(0);
            taskListMenuGroupMapper.updateByPrimaryKey(group);
        }
        return group.getGroupId();
    }

    @Override
    public void deleteGroup(long groupId) {
        TaskListMenuGroup group = taskListMenuGroupMapper.selectByPrimaryKey(groupId);
        group.setDeleteFlag(1);
        taskListMenuGroupMapper.updateByPrimaryKey(group);
    }

    @Override
    public TaskListMenu saveUpdateTaskListMenu(TaskListMenu menu) {
        if (null == menu.getMenuId() || 0 == menu.getMenuId()) {
            // 新增
            menu.setDeleteFlag(0);
            taskListMenuMappler.insert(menu);
        } else {
            menu.setDeleteFlag(0);
            taskListMenuMappler.updateByPrimaryKey(menu);
        }
        return menu;
    }

    @Override
    public long deleteMenu(long menuId) {
        TaskListMenu menu = taskListMenuMappler.selectByPrimaryKey(menuId);
        menu.setDeleteFlag(1);
        taskListMenuMappler.updateByPrimaryKey(menu);
        return menuId;
    }

    @Override
    public TaskListMenu loadMenu(long menuId) {
        return taskListMenuMappler.selectByPrimaryKey(menuId);
    }

}
